<template>
  <a-modal :visible="visible" @cancel="closeAddvideo" @ok="closeAddvideo">
    <a-form :form="form" :label-col="{ span: 5 }" :wrapper-col="{ span: 12 }">
      <a-form-item label="时间">
        <a-date-picker
          style="width: 100%"
          v-decorator="[
          'date',
          { rules: [{ required: true, message: '请输入您的训练场地' }] },
        ]"
        />
      </a-form-item>
      <a-form-item label="场地">
        <a-input
          v-decorator="[
          'place',
          { rules: [{ required: false, message: '请输入您的训练场地' }] },
        ]"
          placeholder="请输入您的训练场地"
        />
      </a-form-item>
      <a-form-item label="分数">
        <a-input
          v-decorator="[
          'grade',
          { rules: [{ required: false, message: '请输入您的训练分数' }] },
        ]"
          placeholder="请输入您的训练分数"
        />
      </a-form-item>
      <a-form-item label="批注">
        <a-input
          v-decorator="[
          'comment',
          { rules: [{ required: false, message: '请输入您的训练批注' }] },
        ]"
          placeholder="请输入您的训练批注"
        />
      </a-form-item>
    </a-form>
    <div>
      <input type="file" :disabled="status !== Status.wait" @change="handleFileChange" />
      <a-button @click="handleUpload" :disabled="uploadDisabled">上传</a-button>
      <a-button @click="handleResume" v-if="status === Status.pause">恢复</a-button>
      <a-button :disabled="status !== Status.uploading || !container.hash" @click="handlePause">暂停</a-button>
    </div>
    <div>
      <div>计算文件 hash</div>
      <a-progress :percent="hashPercentage"></a-progress>
      <div>总进度</div>
      <a-progress :percent="totalPercentage"></a-progress>
    </div>
  </a-modal>
</template>

<script>
const SIZE = 1024 * 1024 * 3; // 切片大小

const Status = {
  wait: "wait",
  pause: "pause",
  uploading: "uploading"
};
const columns = [
  {
    title: "训练次数",
    dataIndex: "time",
    width: "10%",
    scopedSlots: { customRender: "time" }
  }
];

export default {
  filters: {
    transformByte(val) {
      return Number((val / 1024).toFixed(0));
    }
  },
  beforeCreate() {
    this.form = this.$form.createForm(this, { name: "dynamic_form_item" });
    this.form.getFieldDecorator("keys", { initialValue: [], preserve: true });
  },
  data() {
    return {
      visible: true,
      Status: {
        wait: "wait",
        pause: "pause",
        uploading: "uploading"
      },
      container: {
        file: null,
        hash: "",
        worker: null
      },
      hashPercentage: 0,
      data: [],
      uploadedList: [],
      requestList: [],
      status: Status.wait,
      close: false
    };
  },
  computed: {
    uploadDisabled() {
      return (
        !this.container.file ||
        [Status.pause, Status.uploading].includes(this.status)
      );
    },
    uploadPercentage() {
      if (!this.container.file || !this.data.length) return 0;
      const loaded = this.data
        .map(item => item.size * item.percentage)
        .reduce((acc, cur) => acc + cur);
      return parseInt((loaded / this.container.file.size).toFixed(2));
    },
    totalPercentage() {
      if (this.requestList.length !== 0) {
        console.log(
          this.$store.state.totalPercentage,
          this.uploadedList.length,
          this.data.length,
          this.totalPercentage
        );
        return (
          ((this.$store.state.totalPercentage + this.uploadedList.length) /
            this.data.length) *
          100
        );
      }
      if (this.uploadedList.length != 0) {
        return (
          ((this.$store.state.totalPercentage + this.uploadedList.length) /
            this.data.length) *
          100
        );
      } else {
        return 0;
      }
    }
  },
  watch: {
    uploadPercentage(now) {
      if (now > this.fakeUploadPercentage) {
        this.fakeUploadPercentage = now;
      }
    }
  },
  methods: {
    closeAddvideo() {
      this.$emit("closeAddvideo");
      this.resetData();
      this.$store.commit("clearTotal");
      this.close = true;
      this.requestList.length = 0;
      this.uploadedList.length = 0;
    },
    handlePause() {
      this.status = Status.pause;
      this.resetData();
    },
    resetData() {
      this.requestList = [];
      this.close = true;
      if (this.container.worker) {
        this.container.worker.onmessage = null;
      }
    },
    async handleResume() {
      this.status = Status.uploading;
      const { data } = await this.verifyUpload(
        this.container.file.name,
        this.container.hash
      );
      await this.uploadChunks(data);
    },
    requestFailed(err) {
      this.$notification["error"]({
        message: "错误",
        description: "请求出现错误，请稍后再试",
        duration: 4
      });
      this.registerBtn = false;
    },
    // 生成文件切片
    createFileChunk(file, size = SIZE) {
      const fileChunkList = [];
      let cur = 0;
      while (cur < file.size) {
        fileChunkList.push({ file: file.slice(cur, cur + size) });
        cur += size;
      }
      console.log(fileChunkList);

      return fileChunkList;
    },
    // 生成文件 hash（web-worker）
    calculateHash(fileChunkList) {
      return new Promise(resolve => {
        this.container.worker = new Worker("/hash.js");
        this.container.worker.postMessage({ fileChunkList });
        this.container.worker.onmessage = e => {
          const { percentage, hash } = e.data;
          this.hashPercentage = percentage;
          if (hash) {
            resolve(hash);
          }
        };
      });
    },
    handleFileChange(e) {
      const [file] = e.target.files;
      if (!file) return;
      this.resetData();
      Object.assign(this.$data, this.$options.data());
      this.container.file = file;
    },
    async handleUpload() {
      this.close = false;
      if (!this.container.file) return;
      this.status = Status.uploading;
      const fileChunkList = this.createFileChunk(this.container.file);
      this.container.hash = await this.calculateHash(fileChunkList);

      //fileChunkList是生成切片数组
      //this.data是要用formData封装后传给后端的
      this.data = fileChunkList.map(({ file }, index) => ({
        fileHash: this.container.hash,
        index,
        hash: this.container.hash + "-" + index,
        chunk: file,
        size: file.size
        // percentage: uploadedList.includes(index) ? 100 : 0
      }));

      const data = await this.verifyUpload(
        this.container.file.name,
        this.container.hash
      );
      await this.uploadChunks(data.data);
    },
    // 上传切片，同时过滤已上传的切片
    async uploadChunks(uploadedList = []) {
      //得到过滤数组
      let filterArr = this.data.filter(({ hash }) => {
        //这里注意下标是字符,要转成数字
        let arr = hash.split("-");
        return !uploadedList.includes(parseInt(arr[1]));
      });
      console.log("filterArr", filterArr);

      const requestList = filterArr.map(({ chunk, hash, index }) => {
        const formData = new FormData();
        formData.append("chunck", chunk);
        formData.append("num", index);
        // formData.append("hash", hash);
        // formData.append("filename", this.container.file.name);
        formData.append("filehash", this.container.hash);
        return { formData, index };
      });

      this.requestList = requestList;
      let that = this;
      (async function() {
        console.log(666);
        for (let i = 0; i < requestList.length; i++) {
          console.log("i", i);
          console.log(that.close);
          
          if (that.close == true) break;
          await that.$api.video
            .sendslice(requestList[i].formData)
            .catch(error => {
              console.log(error);
              this.requestFailed(error);
            });
        }
      })();

      // 合并切片
      if (this.totalPercentage == 100) {
        await this.mergeRequest();
      }
    },
    // 通知服务端合并切片
    async mergeRequest() {
      let data = {
        filehash: this.container.hash,
        id: "12345",
        date: "",
        comment: "",
        place: "",
        grade: 0
      };
      this.form.validateFields((err, values) => {
        console.log("Received values of form: ", values);
        data.date = values.date._d.toLocaleDateString();
        data.comment = values.comment;
        data.place = values.place;
        data.grade = values.grade;
      });
      await this.$api.video
        .merge(data)
        .then(res => {
          //******************************************************************************************************** */
          // this.createProgressHandler(this.data[index]);
        })
        .catch(error => {
          this.requestFailed(error);
        });
      this.status = Status.wait;
    },
    // 根据 hash 验证文件是否曾经已经被上传过
    // 没有才进行上传
    async verifyUpload(filename, fileHash) {
      const { data } = await this.$api.video.verify({
        filehash: this.container.hash
      });
      console.log("我是当前已经上传的切片下标", data);
      this.uploadedList = data.data;

      return data;
    },
    // 用闭包保存每个 chunk 的进度数据
    createProgressHandler(item) {
      return e => {
        item.percentage = parseInt(String((e.loaded / e.total) * 100));
      };
    }
  }
};
</script>
